package com.ysstech.reportworld.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ysstech.common.entity.PageBean;
import com.ysstech.common.exception.BusinessException;
import com.ysstech.common.service.DicvalueService;
import com.ysstech.common.util.CollectionUtil;
import com.ysstech.reportworld.entity.*;
import com.ysstech.reportworld.enums.ReportWorldEnum;
import com.ysstech.reportworld.enums.ReportWorldStandardCheckTableCodeEnum;
import com.ysstech.reportworld.enums.ReportWorldStatusEnum;
import com.ysstech.reportworld.mapper.TableStandardCheckMapper;
import com.ysstech.reportworld.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 报表世界表校验规则 服务实现类
 * </p>
 *
 * @author lishuangliang
 * @since 2023-01-18
 */
@Service
@Slf4j
public class TableStandardCheckServiceImpl extends ServiceImpl<TableStandardCheckMapper, TableStandardCheck> implements TableStandardCheckService {

    @Autowired
    private TableDetailService tableDetailService;
    @Autowired
    private DicvalueService dicvalueService;
    @Autowired
    private CustomerService customerService;
    @Autowired
    private ReportService reportService;
    @Autowired
    private ModularService modularService;

    /**
     * 获取表校验规则信息
     *
     * @param tableStandardCheck
     * @param pageBean
     * @return
     * @throws Exception
     */
    public PageBean<TableStandardCheck> queryAllTableStandardCheck(TableStandardCheck tableStandardCheck, PageBean pageBean) throws Exception {
        QueryWrapper<TableStandardCheck> wrapper = getQueryWrapper(tableStandardCheck);
        IPage pageScheduleLog = this.page(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()), wrapper);
        this.switchedListTableStandardCheck(pageScheduleLog.getRecords());
        return new PageBean<>(pageScheduleLog);
    }

    /**
     * 处理查询条件信息
     *
     * @param tableStandardCheck
     * @return
     */
    private QueryWrapper<TableStandardCheck> getQueryWrapper(TableStandardCheck tableStandardCheck) {
        if (null == tableStandardCheck) {
            return null;
        }
        QueryWrapper<TableStandardCheck> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(tableStandardCheck.getCheckCode())) {
            wrapper.eq("CHECK_CODE", tableStandardCheck.getCheckCode());
        }
        if (StringUtils.isNotBlank(tableStandardCheck.getTableNamePrefix())) {
            wrapper.like("TABLE_NAME_PREFIX", tableStandardCheck.getTableNamePrefix());
        }
        if (StringUtils.isNotBlank(tableStandardCheck.getTableNameSuffix())) {
            wrapper.like("TABLE_NAME_SUFFIX", tableStandardCheck.getTableNameSuffix());
        }
        if (StringUtils.isNotBlank(tableStandardCheck.getTableNameContain())) {
            wrapper.like("TABLE_NAME_SUFFIX", tableStandardCheck.getTableNameContain());
        }
        if (null != tableStandardCheck.getStatus()) {
            wrapper.eq("STATUS", tableStandardCheck.getStatus());
        }
        return wrapper;
    }

    /**
     * 类型，机构等中文的转换
     *
     * @param list
     * @return
     * @throws Exception
     */
    private List<TableStandardCheck> switchedListTableStandardCheck(List<TableStandardCheck> list) throws Exception {
        if (CollectionUtils.isEmpty(list)) {
            return list;
        }
        //表所在分层
        Map<String, String> mapTableLayered = dicvalueService.getCacheDicValueMap(ReportWorldEnum.REPORT_TABLE_LAYERED.getCode());
        //状态
        Map<String, String> mapStatus = dicvalueService.getCacheDicValueMap(ReportWorldEnum.REPORT_STATUS.getCode());
        Map<String, Customer> mapCustomer = customerService.getCustomerMap();
        Map<String, Report> mapReport = reportService.getReportMap();
        Map<String, Modular> mapModular = modularService.getModularMap();
        for (TableStandardCheck tableStandardCheck : list) {
            if (null == tableStandardCheck) {
                continue;
            }
            //状态
            if (null != mapStatus && mapStatus.containsKey(String.valueOf(tableStandardCheck.getStatus()))) {
                tableStandardCheck.setStrStatus(mapStatus.get(String.valueOf(tableStandardCheck.getStatus())));
            }
            if (StringUtils.isBlank(tableStandardCheck.getCheckCode())) {
                continue;
            }
            ReportWorldStandardCheckTableCodeEnum baseEnum = ReportWorldStandardCheckTableCodeEnum.getEnum(tableStandardCheck.getCheckCode());
            if (null == baseEnum) {
                continue;
            }
            tableStandardCheck.setStrCheckCode(baseEnum.getDesc());
            // 加载对应的值
            switch (baseEnum) {
                case LAYERED:
                    //报表世界所在分层
                    if (null != mapTableLayered && mapTableLayered.containsKey(tableStandardCheck.getCheckValue())) {
                        tableStandardCheck.setStrCheckValue(mapTableLayered.get(tableStandardCheck.getCheckValue()));
                    }
                    break;
             /*   case FTYPE:
                    break;
                case FSOURCE:
                    break;*/
                case CUSTOMER:
                    if (null != mapCustomer && mapCustomer.containsKey(tableStandardCheck.getCheckValue())
                            && null != mapCustomer.get(tableStandardCheck.getCheckValue())) {
                        tableStandardCheck.setStrCheckValue(mapCustomer.get(tableStandardCheck.getCheckValue()).getName());
                    }
                    break;
                case REPORT:
                    if (null != mapReport && mapReport.containsKey(tableStandardCheck.getCheckValue())
                            && null != mapReport.get(tableStandardCheck.getCheckValue())) {
                        tableStandardCheck.setStrCheckValue(mapReport.get(tableStandardCheck.getCheckValue()).getName());
                    }
                    break;
                case MODULAR:
                    if (null != mapModular && mapModular.containsKey(tableStandardCheck.getCheckValue())
                            && null != mapModular.get(tableStandardCheck.getCheckValue())) {
                        tableStandardCheck.setStrCheckValue(mapModular.get(tableStandardCheck.getCheckValue()).getName());
                    }
                    break;
                default:
                    throw new BusinessException("系统没有获取到对应的校验规则");
            }
        }
        return list;
    }


    /**
     * 新增时候检验规范
     *
     * @return
     * @throws Exception
     */
    public void tableStandardCheckInfo(List<Table> list, boolean isDetail) throws Exception {
        if (CollectionUtils.isEmpty(list)) {
            log.error("没有获取到要校验的表信息");
            throw new BusinessException("没有获取到要校验的表信息");
        }
        Map<Object, List<TableStandardCheck>> map = this.getTableStandardCheckMap();
        if (CollectionUtils.isEmpty(map)) {
            log.error("没有获取到要校验的表信息");
            return;
        }
        for (Table table : list) {
            if (null == table || StringUtils.isBlank(table.getName())) {
                continue;
            }
            if (StringUtils.isBlank(table.getChineseName())) {
                throw new BusinessException(table.getName() + "表没有获取到中文名称，请检查！");
            }
            List<String> listEnum = ReportWorldStandardCheckTableCodeEnum.getReportWorldStandardCheckTableEnum();
            for (String code : listEnum) {
                List<TableStandardCheck> checkList = map.get(code);
                if (CollectionUtils.isEmpty(checkList)) {
                    continue;
                }
                this.checktableStandard(table, code, checkList);
            }
            if (isDetail) {
                this.checkTableDetail(table);
            }
        }
    }

    /**
     * 表的校验
     *
     * @param table
     * @throws Exception
     */
    public void tableStandardCheckInfo(Table table, boolean isDetail) throws Exception {
        if (null == table || StringUtils.isBlank(table.getName())) {
            log.error("没有获取到要校验的表信息");
            throw new BusinessException("没有获取到要校验的表信息");
        }
        if (StringUtils.isBlank(table.getChineseName())) {
            throw new BusinessException(table.getName() + "表没有获取到中文名称，请检查！");
        }
        Map<Object, List<TableStandardCheck>> map = this.getTableStandardCheckMap();
        if (CollectionUtils.isEmpty(map)) {
            log.error("没有获取到要校验的表信息");
            return;
        }
        List<String> listEnum = ReportWorldStandardCheckTableCodeEnum.getReportWorldStandardCheckTableEnum();
        for (String code : listEnum) {
            List<TableStandardCheck> checkList = map.get(code);
            if (CollectionUtils.isEmpty(checkList)) {
                continue;
            }
            this.checktableStandard(table, code, checkList);
        }
        if (isDetail) {
            this.checkTableDetail(table);
        }
    }

    /**
     * 检查表时候有字段
     *
     * @param table
     * @throws Exception
     */
    private void checkTableDetail(Table table) throws Exception {
        if (null == table || StringUtils.isBlank(table.getName())) {
            throw new BusinessException("没有获取到表名称信息，请检查！");
        }
        QueryWrapper<TableDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.in("TABLE_ID", table.getId());
        List<TableDetail> listDetail = tableDetailService.list(detailQueryWrapper);
        if (CollectionUtils.isEmpty(listDetail)) {
            throw new BusinessException(table.getName() + "表没有获取字段信息，请检查！");
        }
        List<TableDetail> newListDetail = new ArrayList<>();
        for (TableDetail detail : listDetail) {
            if (!ReportWorldStatusEnum.getUpgradeToolsZipStatus().contains(detail.getStatus())) {
                log.info("升级工具只取正常和已删除状态的数据信息");
                continue;
            }
            newListDetail.add(detail);
            break;
        }
        if (CollectionUtils.isEmpty(newListDetail)) {
            throw new BusinessException(table.getName() + "表没有获取字段信息，请检查！");
        }
    }


    /**
     * 按照检查CODE 存放数据MAP
     *
     * @throws Exception
     */
    private Map<Object, List<TableStandardCheck>> getTableStandardCheckMap() throws Exception {
        QueryWrapper<TableStandardCheck> wrapper = new QueryWrapper();
        wrapper.eq("STATUS", ReportWorldStatusEnum.REPORT_NORMAL.getCode());
        List<TableStandardCheck> checkList = this.list(wrapper);
        if (CollectionUtil.isEmpty(checkList)) {
            log.info("没有获取到表的校验规则信息!");
            return null;
        }
        Map<Object, List<TableStandardCheck>> map = new HashMap<>();
        for (TableStandardCheck check : checkList) {
            if (null == check || StringUtils.isBlank(check.getCheckCode())) {
                continue;
            }
            if (map.containsKey(check.getCheckCode())) {
                List<TableStandardCheck> list = map.get(check.getCheckCode());
                if (!CollectionUtils.isEmpty(list)) {
                    list.add(check);
                    map.put(check.getCheckCode(), list);
                }
            } else {
                List<TableStandardCheck> list = new ArrayList<>();
                list.add(check);
                map.put(check.getCheckCode(), list);
            }
        }
        return map;
    }

    /**
     * 按照类型获取对用的表规则集合
     *
     * @return
     * @throws Exception
     */
    private void checktableStandard(Table table, String code, List<TableStandardCheck> checkList) throws
            Exception {
        ReportWorldStandardCheckTableCodeEnum baseEnum = ReportWorldStandardCheckTableCodeEnum.getEnum(code);
        switch (baseEnum) {
            case LAYERED:
                if (null == table.getLayered()) {
                    break;
                }
                this.checktableStandardInfo(String.valueOf(table.getLayered()), checkList, code, table);
                break;
      /*      case FTYPE:
                if (null == table.getFtype()) {
                    break;
                }
                this.checktableStandardInfo(String.valueOf(table.getFtype()), checkList, code, table);
                break;
            case FSOURCE:
                if (null == table.getFsource()) {
                    break;
                }
                this.checktableStandardInfo(String.valueOf(table.getFsource()), checkList, code, table);
                break;*/
            case CUSTOMER:
                if (StringUtils.isNotBlank(table.getStrCustomer())) {
                    List<String> ids = JSONArray.parseArray(table.getStrCustomer(), String.class);
                    for (String customerId : ids) {
                        this.checktableStandardInfo(customerId, checkList, code, table);
                    }
                    break;
                }
                if (StringUtils.isNotBlank(table.getCustomer())) {
                    this.checktableStandardInfo(table.getCustomer(), checkList, code, table);
                }
                break;
            case REPORT:
                if (StringUtils.isNotBlank(table.getStrReport())) {
                    List<String> ids = JSONArray.parseArray(table.getStrReport(), String.class);
                    for (String reportId : ids) {
                        this.checktableStandardInfo(reportId, checkList, code, table);
                    }
                    break;
                }
                if (StringUtils.isNotBlank(table.getReport())) {
                    this.checktableStandardInfo(table.getReport(), checkList, code, table);
                }
                break;
            case MODULAR:
                if (StringUtils.isNotBlank(table.getStrModular())) {
                    List<String> ids = JSONArray.parseArray(table.getStrModular(), String.class);
                    for (String modularId : ids) {
                        this.checktableStandardInfo(modularId, checkList, code, table);
                    }
                    break;
                }
                if (StringUtils.isNotBlank(table.getModular())) {
                    this.checktableStandardInfo(table.getModular(), checkList, code, table);
                }
                break;
            default:
                throw new BusinessException("系统没有获取到对应的校验规则");
        }
    }

    /**
     * 表信息校验
     */
    private void checktableStandardInfo(String value, List<TableStandardCheck> checkList, String code, Table
            table) throws Exception {
        if (CollectionUtils.isEmpty(checkList) || StringUtils.isBlank(value)) {
            return;
        }
        for (TableStandardCheck check : checkList) {
            if (null == check) {
                continue;
            }
            if (!value.equals(check.getCheckValue())) {
                continue;
            }
            String enumDesc = ReportWorldStandardCheckTableCodeEnum.getEnumDesc(code);
            // 前缀校验
            if (StringUtils.isNotBlank(check.getTableNamePrefix()) && !table.getName().toUpperCase().startsWith(check.getTableNamePrefix())) {
                throw new BusinessException(enumDesc + "，表前缀不规范，规则中表的前缀必须是" + check.getTableNamePrefix());
            }
            if (StringUtils.isNotBlank(check.getTableNameSuffix()) && !table.getName().toUpperCase().endsWith(check.getTableNameSuffix())) {
                throw new BusinessException(enumDesc + "，表后缀不规范，规则中表的后缀必须是" + check.getTableNamePrefix());
            }
            if (StringUtils.isNotBlank(check.getTableNameContain()) && table.getName().toUpperCase().indexOf(check.getTableNameContain()) <= -1) {
                throw new BusinessException(enumDesc + "，表名不规范，规则中表的名字必须包含" + check.getTableNameContain());
            }
        }

    }

}
